#include "battlesystem.h"

CEntityInterface * g_pEntInterface = NULL;

void SetBattleSystemEntityInterface( CEntityInterface * ent )
{
	
	g_pEntInterface = ent;
	
}

void CBattleSystem::Input( SDL_Event & ev, Uint8 * keys )
{
	
	if( !m_bBattleLocked && m_BattleMenu && m_pCurBattlePlayer->ActionMeterFull() )
	{
		
		m_BattleMenu->Input( ev, keys );
	
		int selected = -1;
		
		if( ( selected = m_BattleMenu->GetOptionMenu()->PollSelected() ) > -1 )
		{
			
			m_pCurBattlePlayer->SetActionMeter( 0.0f );
			
			QueueAttack( m_vPlayers[0], m_vEnemies[0], m_vPlayers[0]->GetBattleData()->GetMove( 1 ) );
		
		//	Vector2D p = m_vPlayers[0]->GetPos();
			
		//	std::string s = m_pCurBattlePlayer->GetBattleData()->GetMove( 1 )->GenerateMoveText( m_vPlayers[0]->GetBattleData()->GetNiceName() );
		//	Lua::BattleText( s.c_str(), 2400, 3 );
			
		}
		
	}
		
}

void CBattleSystem::InitResources()
{
	
	
	if( m_FontName == NULL )
	{
		
		m_FontName = g_pEntInterface->Graphics()->GetFont( "Uni16Bold" );
		m_FontReg = g_pEntInterface->Graphics()->GetFont( "Uni14" );
		m_FontSmall = g_pEntInterface->Graphics()->GetFont( "Uni10" );
		
	}
	
	if( m_MenuBoxMat == NULL )
	{
		
		m_MenuBoxMat = g_pEntInterface->Graphics()->Find( "Graphics/UI/uigeneric.png" );
		m_BackgroundMat = g_pEntInterface->Graphics()->Find( "Graphics/Backgrounds/2DRPG/snowmountain.png" );
		
	}
	
	m_BattleMenu = new CUIBattleMenu;
	
	m_BattleMenu->SetEntityInterface( g_pEntInterface );
	m_BattleMenu->SetMaterial( m_MenuBoxMat );
	
	m_BattleMenu->SetPos( 510, 355 );
	m_BattleMenu->SetPadding( 20, 12 );
	
	m_BattleMenu->SetDrawWindow( false );
	
	m_BattleMenu->InitOptionMenu();
	m_BattleMenu->GetOptionMenu()->SetFont( m_FontReg );
	m_BattleMenu->GetOptionMenu()->SetChosenFont( m_FontName );
	
	FillCurrentPlayerMoveMenu();

	
}

void CBattleSystem::FillCurrentPlayerMoveMenu()
{
	
	if( m_pCurBattlePlayer == NULL )
		return;
	
	m_BattleMenu->GetOptionMenu()->ResetOptions();
	
	m_pCurBattlePlayer->GetBattleData()->IterateMoveList();
	CBattleAttackData * ad = NULL;

	while( ( ad = m_pCurBattlePlayer->GetBattleData()->NextMove() ) != NULL )
	{
		
		m_BattleMenu->GetOptionMenu()->AddOption( ad->GetID(), ad->GetMenuText() );
		
	}
	
	m_BattleMenu->Resize();
	
}

void CBattleSystem::GenerateHit( int attackerid, int victimid, int count )
{
	
	CBattleEntity * attacker = ( CBattleEntity * )m_pEntityFactory->GetStateVec()->GetEntity( attackerid );
	CBattleEntity * victim = ( CBattleEntity * )m_pEntityFactory->GetStateVec()->GetEntity( victimid );
	
	if( attacker->IsDoingAttack() )
	{
		
		CBattleAttackData * ad = attacker->GetCurAttack();
		int c = ad->GenerateRepeatCount();
		
		if( count > 0 )
			c = count;
		
		Vector2D attackerpos = attacker->GetPos();
		Vector2D pos = victim->GetCenter();
		Vector2D size = victim->GetSize();
		
		victim->PainFlash( 400 );
		
		for( int j = 0; j < c; j++ )
		{
			
			
			int power = ad->GenerateDamage( attacker->GetBattleData()->GetPower() );
			
			victim->Damage( power );
			
			char s[255];
			
			sprintf( s, "%d", power );
			
			Lua::PopupText( s, pos.x + Util::random( size.x * -.5f, size.x * .25f ), pos.y + Util::random( size.y * -.5f, size.y * .25f ), 400, 500 );
			//Lua::PopupText( ad->GenerateMoveText( attacker->GetNiceName() ), attackerpos.x, attackerpos.y, 200, 200 );
	
		}
		
		Lua::SetEntityLuaTableValue_Int( victimid, "NextIdleMsg", -1 );
		/*
		if( victim->GetHealthPercent() <= .3 && !Lua::GetEntityLuaTableValue_Bool( victimid, "CritInjured" ) && victim->GetHealthPercent() > 0.0 )
		{
			
			int w = m_FontReg->GetStringWidth( "Critically Injured!" );
			
			//Lua::DelayedTimedUIMessage( "Critically Injured!", pos.x - w / 2, victim->GetPos().y - 20, w + 5, 1200, 0 );
			
			Lua:SetEntityLuaTableValue_Bool( victimid, "CritInjured", true );
			
		}*/
		
	
		
	}
	
}

void CBattleSystem::StartBattle()
{
	
	m_bStartBattle = true;
	m_bBattleDone = false;
	m_bTransitionDone = false;
	
	Lua::SetGlobalBool( "RPGBattle", true );
	
	FillCurrentPlayerMoveMenu();
	
	m_bSkipOuttroTransition = false;
	
}

void CBattleSystem::EndBattle()
{
	
	if( m_BattleExitFunc >= 0 )
		Lua::CallFunction( m_BattleExitFunc );
	
	m_bStartBattle = false;
	m_bBattleDone = true;
	
	m_BattleThinkFunc = -1;
	m_BattleExitFunc = -1;
	
	Lua::SetGlobalBool( "RPGBattle", false );
	
}

void CBattleSystem::CleanBattle()
{
	
	m_pCurBattlePlayer = NULL;
	
	m_vBattleAttackQueue.clear();
	
	for( std::vector< CBattleEntity * >::iterator iter = m_vPlayers.begin();
		 iter != m_vPlayers.end(); iter++ )
		{
			
			m_pEntityFactory->GetStateVec()->RemoveEntity( ( *iter )->GetUniqueID() );
			
		}

	for( std::vector< CBattleEntity * >::iterator iter = m_vEnemies.begin();
		 iter != m_vEnemies.end(); iter++ )
		{
			
			m_pEntityFactory->GetStateVec()->RemoveEntity( ( *iter )->GetUniqueID() );
			
		}
		
	m_vPlayers.clear();
	m_vEnemies.clear(); 
		
}

void CBattleSystem::QueueAttack( CBattleEntity * p, CBattleEntity * ent, CBattleAttackData * ad )
{
	
	if( ent->GetHealth() <= 0 )
		return;
	
	CQueuedBattleAttack * attack = new CQueuedBattleAttack( p, ent, ad );
	
	Lua::CreateAttackThinkData( p->GetUniqueID(), ad->GetID() );
	
	m_vBattleAttackQueue.push_back( attack );

}

//type = 1 for enemy, 0 for player
void CBattleSystem::DetermineBattlePos( int type, CBattleEntity * ent )
{

	Vector2D size = ent->GetSize();
	
	if( type )
	{
		
		static bool s_AltYPos = false;

		int x = Util::random( 1, 10 ) * Util::random( 20, 45 );
		int y = Util::random( 450, 470 );

		if( s_AltYPos )
			y = Util::random( 470, 510 );
			
		s_AltYPos = !s_AltYPos;
		
		ent->SetPos( x, y - size.y );
		
		
	} else
	{

		int x = Util::random( 500, 650 );
		int y = Util::random( 460, 590 - BATTLETRANSITION_HEIGHT );
		
		ent->SetPos( x, y - size.y );
		
	}
	
}

//type = 1 for enemy, 0 for player
CBattleEntity * CBattleSystem::AddBattleEntity( int type, std::string entclass )
{
	
	CBattleCharacterData * bd = m_pBattleStats->GetBattleStats( entclass );
	
	if( bd )
	{

		CBattleEntity * ent = new CBattleEntity;
		ent->SetEntityInterface( g_pEntInterface );
		
		ent->SetBattleStats( bd );
		ent->BindBattleStats();
		
		DetermineBattlePos( type, ent );
		
		ent->SetHasShadow( true );
		
		ent->SetShadowScale( .7, .1 );
		
		if( type )
		{
			ent->SetShadowScale( 1.5, .1 );
			ent->Flip();
			ent->SetShadowOffset( -16, -4 );
			m_vEnemies.push_back( ent );
			
		} else
		{
			ent->SetShadowOffset( 27, -22 );
			m_vPlayers.push_back( ent );
		}
		

		return ent;
	
	}
	
	return NULL;
	
}

void CBattleSystem::AttackQueueThink()
{
	
	for( std::vector< CQueuedBattleAttack * >::iterator iter = m_vBattleAttackQueue.begin();
		 iter != m_vBattleAttackQueue.end();)
		{
			
			bool removed = false;
			
			CBattleEntity * attacker = ( *iter )->GetAttacker();
			CBattleEntity * victim = ( *iter )->GetVictim();
			CBattleAttackData * ad = ( *iter )->GetAttack();
			
			if( attacker->IsDoingAttack() )
			{
			
				CBattleAttackData * curad = attacker->GetCurAttack();
				
				if( curad == ad )
				{
				
					int id = curad->GetThinkFuncID();
					
					if( !Lua::AttackThinkFunc( id, attacker->GetUniqueID(), victim->GetUniqueID(), curad->GetID() ) )
					{
						
						iter = m_vBattleAttackQueue.erase( iter );
						
						removed = true;
						
						attacker->SetCurAttack( NULL );
						victim->SetBeingAttacked( false );
						
					} else if( !victim->BeingAttacked() )
						victim->SetBeingAttacked( true );
				
				}
				
			} else if( !victim->IsDoingAttack() )
			{
				
				attacker->SetCurAttack( ad );
			
				std::string s = ad->GenerateMoveText( attacker->GetBattleData()->GetNiceName() );
				Lua::BattleText( s.c_str(), 2400, 3 );
				
			}
				
			if( ad->CanStopQueue() )
				break;
			else if( !removed )
				iter++;
			
			removed = false;
			
		}
	
}

void CBattleSystem::BindWithEntityFactory()
{

	
	for( std::vector< CBattleEntity * >::iterator iter = m_vEnemies.begin();
		 iter != m_vEnemies.end(); iter++ )
		{
			
			m_pEntityFactory->GetStateVec( 2 )->AddEntity( ( *iter ) );
			
		}
		
	for( std::vector< CBattleEntity * >::iterator iter = m_vPlayers.begin();
		 iter != m_vPlayers.end(); iter++ )
		{
			
			m_pEntityFactory->GetStateVec( 2 )->AddEntity( ( *iter ) );
			
		}
	
}

void CBattleSystem::Think()
{
	
	for( std::vector< CBattleEntity * >::iterator iter = m_vEnemies.begin();
		 iter != m_vEnemies.end(); )
		{
			
			if( m_bBattleLocked )
			{
				
				( *iter )->BaseThink();
				iter++;
				
			} else
			{
				
				( *iter )->Think();
				
				if( ( *iter )->ActionMeterFull() && !( *iter )->BeingAttacked() && ( *iter )->GetHealth() > 0 )
				{
					
					QueueAttack( ( *iter ), m_pCurBattlePlayer, ( *iter )->GetBattleData()->GetMove( 1 ) );
					( *iter )->SetActionMeter( 0.0f );
					
				}
				
				if( ( *iter )->GetHealth() <= 0 && !( *iter )->BeingAttacked() )
				{
					
					if( !( *iter )->DeathFading() )
					{
						Vector2D pos = ( *iter )->GetCenter();
						//		Lua::DelayedTimedUIMessage( "RIP!", pos.x - 25, ( *iter )->GetPos().y - 20, 30, 1200, 0 );
						( *iter )->DeathFade();
						iter++;
					} else if( ( *iter )->DeathFadedOut() )
					{
						m_pEntityFactory->GetStateVec()->RemoveEntity( ( *iter )->GetUniqueID() );
						iter = m_vEnemies.erase( iter );
					} else
						iter++;
					
				} else
					iter++;
			
			}
			
		}
		
	for( std::vector< CBattleEntity * >::iterator iter = m_vPlayers.begin();
		 iter != m_vPlayers.end(); )
		{
			
			if( m_bBattleLocked )
			{
				
				( *iter )->BaseThink();
				iter++;
				
			} else
			{
				
				( *iter )->Think();
				
				if( ( *iter )->GetHealth() <= 0 )
					iter = m_vPlayers.erase( iter );
				else
					iter++;
			}
			
		}
		
	if( !m_bBattleLocked )
	{
	
		AttackQueueThink();
	
			
		if( m_vEnemies.size() == 0 &&
		m_vBattleAttackQueue.size() == 0 )
			EndBattle();
	
	}
		
	if( m_bTransitionDone &&  m_BattleThinkFunc >= 0 )
		Lua::CallFunction( m_BattleThinkFunc );
	
	
}

void CBattleSystem::DrawBackground()
{
	
	Draw::Color4f( 1.0f, 1.0f, 1.0f, 1.0f );
		
	m_BackgroundMat->BindFrame( 0 );
		
	Draw::TexturedQuad( 0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT );
	
	
}

void CBattleSystem::DrawHUD()
{
	
	if( !m_bTransitionDone )
		m_bTransitionDone = true;
	
	PUSH_MATRIX;
	
	for( std::vector< CBattleEntity * >::iterator iter = m_vPlayers.begin();
		 iter != m_vPlayers.end(); iter++ )
		{
			
			Vector2D pos = ( *iter )->GetPos();
			Vector2D cpos = ( *iter )->GetCenter();
			int name_width = m_FontName->GetStringWidth( ( *iter )->GetNiceName() );
			
			char hptext[15];
			sprintf( hptext, "%d", ( *iter )->GetHealth(), ( *iter )->GetMaxHealth() );
			
			int hp_width = m_FontSmall->GetStringWidth( hptext );
			
			Draw::Color4f( 1.0f, 1.0f, 1.0f, 1.0f );
			
			m_FontName->Draw( ( *iter )->GetNiceName(), cpos.x - ( int )( name_width * .4 ), pos.y - 50 );
			m_FontSmall->Draw( hptext, cpos.x, pos.y - 30 );
			
			Draw::DisableTextures();
			
			float h_mul = ( *iter )->GetHealthPercent();
			float am_mul = ( *iter )->GetActionMeter() / 100.0f;

			Draw::Color4f( 1.0f, 1.0f, 1.0f, 1.0f );
			Draw::Quad( cpos.x + hp_width + 3, pos.y - 28, 0.0f, 60.0f, 10.0f );
			
			Draw::Color4f( 0.5f, 0.0f, .0f, .7f );
			Draw::Quad( cpos.x + hp_width + 6, pos.y - 25, 0.0f, 54.0f * h_mul, 4.0f );
			
			
			Draw::Color4f( 1.0f, 1.0f, 1.0f, 1.0f );
			Draw::Quad( cpos.x + hp_width + 3, pos.y - 15, 0.0f, 60.0f, 10.0f );
			
			Draw::Color4f( 0.0f, 0.0f, .5f, .7f );
			Draw::Quad( cpos.x + hp_width + 6, pos.y - 12, 0.0f, 54.0f * am_mul, 4.0f );
			
			Draw::EnableTextures();
		
		}
		
	/*
	Draw::DisableTextures();
		
	for( std::vector< CBattleEntity * >::iterator iter = m_vEnemies.begin();
		 iter != m_vEnemies.end(); iter++ )
		{
			
			Draw::Color4f( 1.0f, 1.0f, 1.0f, 1.0f );
			
			Vector2D pos = ( *iter )->GetCenter();
			
			//m_FontName->Draw( ( *iter )->GetNiceName(), pos.x, pos.y -20.0 );
	
			
			
			Draw::Color4f( 1.0f, 1.0f, 1.0f, 1.0f );
			//Draw::Quad( pos.x - 30, ( *iter )->GetPos().y, 0.0f, 60.0f, 10.0f );
			
			Draw::Color4f( 0.4f, 0.0f, .0f, 1.0f );
			//Draw::Quad( pos.x - 27, ( *iter )->GetPos().y + 3, 0.0f, 54.0f, 4.0f );
			
		}
		
	Draw::EnableTextures();
	*/
	
	POP_MATRIX;
	
	Draw::Color4f( .7f, .7f, .7f, .5f );	
	
	if( m_pCurBattlePlayer->ActionMeterFull() )
	{
		
		Vector2D pos = m_pCurBattlePlayer->GetCenter();
		m_BattleMenu->SetPos( pos.x - 130, pos.y - 50 );
		m_BattleMenu->Resize();
		m_BattleMenu->Draw();
		
	}
	
	/*
	
	if( m_FontName )
	{
		
		glColor4f( .7f, .7f, .7f, .5f );
		
		//m_MenuBoxMat->BindFrame( 0 );
		//Draw::TexturedQuad( 390.0f, 390.0f, 90.0f, SCREEN_HEIGHT - BATTLETRANSITION_HEIGHT - 390.0f );
		
		if( m_pCurBattlePlayer->ActionMeterFull() )
			m_BattleMenu->Draw();
		
		glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
		
		float yoffset = 0.0f;
		
		for( std::vector< CBattleEntity * >::iterator iter = m_vEnemies.begin();
		 iter != m_vEnemies.end(); iter++ )
		{
		
			m_FontReg->Draw( ( *iter )->GetNiceName(), 10.0f, 400.0f + yoffset );
			yoffset += 15.0f;
			
		}
		
		yoffset = 0.0f;
		
		for( std::vector< CBattleEntity * >::iterator iter = m_vPlayers.begin();
		 iter != m_vPlayers.end(); iter++ )
		{
			
			char hptext[15];
			sprintf( hptext, "%d / %d", ( *iter )->GetHealth(), ( *iter )->GetMaxHealth() );
			
			m_FontName->Draw( ( *iter )->GetNiceName(), 500.0f, 400.0f + yoffset );
			m_FontReg->Draw( hptext, 640.0f, 400.0f + yoffset );
		
			glDisable( GL_TEXTURE_2D );
			
			float am_mul = ( *iter )->GetActionMeter() / 100.0f;
			
			glColor4f( 0.0f, 0.0f, 0.0f, 1.0f );
			Draw::Quad( 720.0f, 404.0f, 0.0f, 60.0f, 10.0f );
			
			glColor4f( 0.0f, 0.0f, .5f, .7f );
			Draw::Quad( 721.0f, 405.0f, 0.0f, 58.0f * am_mul, 8.0f );
			
			glColor4f( 0.4f, 0.4f, .7f, .7f );
			Draw::Quad( 721.0f, 405.0f, 0.0f, 58.0f * am_mul, 4.0f );
			
			glEnable( GL_TEXTURE_2D );
		
			yoffset += 15.0f;
		
		}
		
		m_FontReg->Draw( "> Attack!", 400.0f, 400.0f );
		
		glColor4f( .6f, .6f, .6f, 0.4f );
		
		m_FontReg->Draw( "Use Item", 400.0f, 420.0f );
		m_FontReg->Draw( "Run!", 400.0f, 440.0f );
		
		glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
		
	}

	*/
	
}

void CBattleSystem::DrawEntities()
{
	
	/*
	for( std::vector< CBattleEntity * >::iterator iter = m_vEnemies.begin();
		 iter != m_vEnemies.end(); iter++ )
		{
			
			( *iter )->Draw();
						
		}
		
	for( std::vector< CBattleEntity * >::iterator iter = m_vPlayers.begin();
		 iter != m_vPlayers.end(); iter++ )
		{
			
			( *iter )->Draw();
			
		}
	
	*/
	
	m_pEntityFactory->GetStateVec( 2 )->DrawEntitiesRaw();
	
}
